package search;

import agents.AgentState;
import agents.AutomatonAgent;
import env.Action;
import env.Enviroment;
import env.Tile;
import java.util.Vector;

/**
 * @author orcas
 */
public class SearchState {
    AgentState myState;
    AgentState sentryState;
    private Vector<Tile> flags; //available flags
    public boolean capture;
    public boolean isAlive;

    public SearchState(AgentState myState, AgentState sentryState, Vector<Tile> flags, boolean capture, boolean isAlive) {
        this.myState=myState;
        this.sentryState=sentryState;//new AgentState(sentry.getRow(), sentry.getCol(), sentry.getOrientation());
        this.flags = flags; 
        this.capture=capture;
        this.isAlive=isAlive;
    }

    SearchState clone(Action move) {
        final AgentState nextMyState = myState.clone(move);
        final Tile nextTile = nextMyState.getTile();
        final Vector<Tile> nextFlags;
        boolean nextCapture=false;
        if (flags.contains(nextTile)) {
            nextCapture=true;
                nextFlags = new Vector<Tile>(flags.size()-1);
                for (Tile f : flags) {
                    if (f != nextTile) {
                        nextFlags.add(f);
                    }
                }
            }
        else nextFlags=flags;
        //TODO: sentry factory
        final AgentState nextSentryState = sentryState.clone(AutomatonAgent.nextMove(sentryState));
        boolean nextIsAlive=//sentryState.getTile().hasLOSwith(nextSentryState.getTile());
            !Enviroment.env.isInLineOfSight(nextMyState.getRow(), nextMyState.getCol(), sentryState.getRow(), sentryState.getCol());
          //a thought: is that the right way to check in the sequential system?
        return new SearchState(nextMyState, nextSentryState, nextFlags, nextCapture, nextIsAlive);
    }

    public Tile getTile(){
        return myState.getTile();
    }

    Vector<Tile> getFlags() {
        return flags;
    }

    @Override
    public boolean equals(Object obj) {
        final SearchState other = (SearchState) obj;
        if (this.myState != other.myState && !this.myState.equals(other.myState)) {
            return false;
        }
        //TODO: it's enough to check sentry's col
        if (this.sentryState != other.sentryState && !this.sentryState.equals(other.sentryState)) {
            return false;
        }
        if (this.flags != other.flags && !this.flags.equals(other.flags)) {
            return false;
        }
//        if (this.isAlive != other.isAlive) {
//            return false;
//        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 29 * hash + this.myState.hashCode();
        hash = 29 * hash + this.sentryState.hashCode(); //TODO: sentryState.getCol();
        hash = 29 * hash + this.flags.hashCode();
//        hash = 29 * hash + (this.isAlive ? 1 : 0);
        return hash;
    }
    
        @Override
    public String toString() {
        return "I'm at " + myState + ",  sentry at " + (sentryState != null ? sentryState.getCol() : "nowhere!") + "  #f=" + flags.size() + " alive?=" + isAlive +(capture?" ~~~~ capture! ~~~~":"");
    }
    

}
